<?php 

/**
 * This File represents basic communication to obtain the services status for the 
 * MTA Transit Status
 * 
 * The service status is updated every 4 minutes and can be viewed at: http://mta.info/status/serviceStatus.txt
 *
 * @author Albert Rosa <rosalbert@rokkan.com>
 * @version 0.1.1
 * @since 5/6/2010
 *
 * @license http://albert-rosa.com/license/BSDLicense.rtf
 *
 * Copyright (c) 2010, Albert Rosa
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 *	•	Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 *	•	Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
 *	•	Neither the name Nanaly, Zend_Mta Albert Rosa nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 /**
 * @see Mta_Exception
 **/
 require_once 'Mta/Exception.php';


/**
 * This class abstracts the xml feed to easily manage the status by line and purpose
 */
 class Mta_Service_Status{
	
	/**
     * @var string constant for subway feed
     */
	const TRAIN ="subway";

    /**
     * @var string constant for bus feed
     */
	const BUS = "bus";

    /**
     * @var string constant for BT feed
     */
	const BT = "BT";

    /**
     * @var string constant for LIRR feed
     */
	const LIRR = "LIRR";

    /**
     * @var string contant for MetroNorth feed
     */
	const METRONORTH = "MetroNorth";

	
	/**
	 * This is the container for the zend_feed object
	 * @var SimpleXMLElement
	 */
	private $_feed;
	
	/**
	 * This is the container for the content
	 * @var string
	 */
	private $_xml;
	
	/**
	 * This is the container for the location of where we obtain the status changes
	 * @var string
	 */
	private $_serviceStatusUrl = 'http://mta.info/status/serviceStatus.txt';

	/**
	 * This is the basic constructor which sets the statusUrl if the url happens to change
	 * Here we also set the the feed and the xml object to handle the response 
	 *
	 * @param string $serviceStatusUrl the replace the current url being used
	 */
	public function __construct($serviceStatusUrl = null)
	{
		if($serviceStatusUrl)
			$this->_serviceStatusUrl = $serviceStatusUrl;
			
		if($this->_serviceStatusUrl == null)
			throw new Mta_Exception('The Service url must be set');
			
		try{
			$this->_xml = file_get_contents($this->_serviceStatusUrl);
			$this->_feed = simplexml_load_string($this->_xml);
			
			if( $this->_xml == NULL || $this->_feed == NULL)
				throw new Mta_Exception('The Service could not establish communication with MTA Server');
			
		}catch(Exception $e)
		{
			throw new Mta_Exception('The Service could not establish communication with MTA Server');
		}
	}
	
	/**
	 * This function returns the full Zend_Feed object or the xml feed if the xml flag is set
	 *
	 * @param boolean $asXml set to true if you wish to obtain the xml feed
	 * @return Zend_Feed|string 
	 */
	public function getFeed($asXml = false)
	{
		if($asXml)
			return $this->_xml;
		
		return $this->_feed;
	}
	
	/**
	 * This function returns the MTA's Service Status Url
	 *
	 * @return string
	 */
	public function getStatusUrl()
	{
		return $this->_serviceStatusUrl;
	}
	
	/**
	 * This function obtains the the train line status
	 * You can set $trainLine to 'NULL' to return all the current status, a string of just 1 line you are inquiring 
	 * about, or an array of all the lines you are interested about
	 *
	 * @param string|array $trainLine
	 * @return string|array returns a string if one line is requested; return an array if null or an array of lines are requested
	 * @deprecated 2010-06-13
	 **/
	public function getStatusByTrain($trainLine = null)
	{
		throw New Mta_Exception('getStatusByTrain has been deprecated please use: getTrainStatus()');
		return $this->getStatus(self::TRAIN, $trainLine);
		
	}
	
	
	/**
	 * This function obtains the the train line status
	 * You can set $trainLine to 'NULL' to return all the current status, a string of just 1 line you are inquiring 
	 * about, or an array of all the lines you are interested about
	 *
	 * @param string|array $trainLine
	 * @return string|array returns a string if one line is requested; return an array if null or an array of lines are requested
	 */
	public function getTrainStatus($trainLine = null)
	{
		return $this->getStatus(self::TRAIN, $trainLine);
	}
	
	/**
	 * This will return the full information of the train line
	 *
	 * <code>
	 * array signature 
	 * 	
	 *	$result['status']  status of the train
	 *	$result['text'] extra detailed text
	 *	$result['url'] url for status link
	 *	$result['date'] date of status
	 *	$result['time'] = status timestamp
	 *
	 *
	 * @return array
	 * @author Albert Rosa <rosalbert@gmail.com>
	 * @deprecated 2010-06-12
	 **/
	public function getInfoByTrain($trainLine = null)
	{
		throw New Mta_Exception('getInfoByTrain has been deprecated please use: getTrainInfo()');
		return $this->getInfo(self::TRAIN, $trainLine);
	}
	
	
	
	/**
	 * This will return the full information of the train line
	 *
	 * <code>
	 * array signature 
	 * 	
	 *	$result['status']  status of the train
	 *	$result['text'] extra detailed text
	 *	$result['url'] url for status link
	 *	$result['date'] date of status
	 *	$result['time'] = status timestamp
	 *
	 *
	 * @return array
	 * @author Albert Rosa <rosalbert@gmail.com>
	 **/
	public function getTrainInfo($trainLine = null)
	{
		return $this->getInfo(self::TRAIN, $trainLine);
	}
	
	
	/**
	 * This obtains the busses information from the status fields
	 * 
	 * @param $busLine string|array
	 * @author Albert Rosa <rosalbert@gmail.com>
	 */
	public function getBusStatus($busLine = null)
	{
		return $this->getStatus(self::BUS, $busLine);
	}
	
	
	/**
	 * Checks to see if the line is identical
	 *
     * @param string $line
     * @param string $lineName
	 * @return boolean
	 * @author Albert Rosa <rosalbert@gmail.com>
	 **/
	private function isLine($line, $lineName)
	{
        $line = (string)$line;
        $lineName = (string)$lineName;

		$myLineRoute = str_replace(array(1,2,3,4,5,6,7,8,9,0,' ','-'), '', $line);
        $myLineRoute .= $myLineRoute;
		$lineRoute = str_replace(array(1,2,3,4,5,6,7,8,9,0,' ', '-'), '', $lineName);

		if(strtolower($line) == strtolower($lineName))
		{
			return True;
		}elseif(!empty($myLineRoute) && strtolower($myLineRoute) == strtolower($lineRoute)){

            return True;
		}elseif(strpos ($lineName , $line)> -1)
		{
			return True;
		}else{
			return False;
		}
		
	}
	
	
	/**
	 * Gets the bus information
	 *
	 * @return array|mixed
	 */
	public function getBusInfo($busLine = null)
	{
		return $this->getInfo(self::BUS, $busLine);
	}

    /**
     * This obtains the information for the $type of information you
     * are in search of.
     *
     * @param string $type
     * @param string|array $lineName
     * @return array
     */
	private function getInfo($type = self::TRAIN, $lineName= null)
	{
		// Here we handle obtaining the train information status if its an array
		if(is_array($lineName) && !empty($lineName))
		{
			$results =  array();
			foreach($lineName as $line){
				$results[$line] = $this->getInfo($type, $line);
			}
			return $results;
		}else
		
		//here we handle obtaining the train information if the $trainLine is null or and empty array
		//@todo traverse through the zend Feed and obtain the line and status pairs
		if(empty($lineName))
		{

			$results =  array();
			foreach($this->_feed->$type->line as $line)
			{
				$results
					[(string)$line->name] = $this->getInfo($type, (string)$line->name);
			}
			return $results;
		}else
		
		// here we handle obtaining the train information by the line only 1 was set
		//@todo travers through the feed looking for the line
		if($lineName)
		{
			$result = array();
			//@todo should be something along these lines
			foreach($this->_feed->$type->line as $line)
			{	
				if($this->isLine($lineName, (string)$line->name))
				{
					$result['status'] = (string)$line->status;
					$result['text'] = (string)$line->text;
					$result['url'] = (string)$line->url;
					$result['date'] = (string)$line->Date;
					$result['time'] = (string)$line->Time;
				}
				
			}
			return $result;
		}
	}

    /**
     * This ontains the status of the $type of information you
     * are in search of.
     *
     * @param string $type
     * @param string $lineName
     * @return string
     */
    private function getStatus($type = self::TRAIN, $lineName=null)
    {
        // Here we handle obtaining the $type information status if its an array
		if(is_array($lineName) && !empty($lineName))
		{
			$results =  array();
			foreach($lineName as $line){
				$results[$line] = $this->getStatus($type, $lineName);
			}
			return $results;
		}else

		//here we handle obtaining the train information if the $linename
        //is null or and empty array
		if(empty($lineName))
		{
			$results =  array();
			foreach($this->_feed->$type->line as $line)
			{
				$results
					[(string)$line->name] =
					(string)$line->status;
			}
			return $results;
		}else

		// here we handle obtaining the $type information by the
        // line only 1 was set
		if($lineName)
		{
			$result = null;
			//@todo should be something along these lines
			foreach($this->_feed->$type->line as $line)
			{
				if($this->isLine($lineName, $line->name)){
					$result = (string)$line->status;
				}
			}
			return $result;
		}
    }
	
	/**
     * This obtains the status for the BT lines
     *
     * @param string|array $btLine
     * @return array
     */
	public function getBTStatus($btLine = null)
	{
        
		return $this->getStatus(self::BT, $btLine);
    }

    /**
     * This obtains the Info for the BT lines
     *
     * @param array|string $btLine
     * @return array
     */
	public function getBTInfo($btLine = null)
	{
        
		return $this->getInfo(self::BT, $btLine);
    }

    /**
     * This obtains the LIRR status
     *
     * @param string|array $lirrLine
     * @return array|string
     */
	public function getLIRRStatus($lirrLine = null)
	{
		return $this->getStatus(self::LIRR, $lirrLine);
    }

    /**
     * This obtains the Information for the LIRR
     *
     * @param string|array $lirrLine
     * @return array|
     */
	public function getLIRRInfo($lirrLine = null)
	{
        
		return $this->getInfo(self::LIRR, $lirrLine);
    }

    /**
     * This returns the status of the metro north line
     * 
     * @param string|array $metroNorthLine
     * @return string|array
     */
	public function getMetroNorthStatus($metroNorthLine= null)
	{
		return $this->getStatus(self::METRONORTH, $metroNorthLine);
    }


    /**
     * This returns the information for the metro north line
     *
     * @param string|array $metroNorthLine
     * @return array
     */
	public function getMetroNorthInfo($metroNorthLine = null)
	{
		return $this->getInfo(self::METRONORTH, $metroNorthLine);
    }
	
	
	
}


